---
title: One Simple Trick to Cleaning Up Tailwind CSS Code (v3)
description: Learn how to clean up repetitive Tailwind CSS classes in your markup by using the child selector variant to delegate styles to parent elements.
emoji: 🧼
slug: how-to-clean-up-tailwindcss-code
pubDate: 2022-10-07
updatedDate: 2025-10-16
terms:
  - refactoring
  - selector
  - jit
---

import BaseAd from '../../components/BaseAd.astro'

<BaseAd />

**[This is outdated since Tailwind CSS 3.4](https://tailwindcss.com/blog/tailwindcss-v3-4#style-children-with-the-variant)**

Tailwind CSS can make your markup messy. However, we can prevent this by
delegating classes to the parent element.

Let's take the following example.

```html
<ul>
  <li class="text-sm font-medium text-gray-900">...</li>
  <li class="text-sm font-medium text-gray-900">...</li>
  <li class="bg-gray-100 text-sm font-medium text-gray-900">...</li>
</ul>
```

We have three repeating classes on the `<li>` elements.

- `text-sm`
- `font-medium`
- `text-gray-900`

We can clean this up by moving these classes to the parent `<ul>` element and
letting the CSS cascade down.

```html
<ul class="text-sm font-medium text-gray-900">
  <li>...</li>
  <li>...</li>
  <li class="bg-gray-100">...</li>
</ul>
```

But what if we are using classes that cannot be delegated to the parent? Classes
like `whitespace-nowrap`, `px-8`, `rotate-3` and many more cannot be applied to
child elements through cascading. Thankfully, there's a solution...

## Enter Tailwind CSS JIT

If you're uncertain about JIT, you can refer to my blog
[What is JIT in Tailwind CSS?](/blog/what-is-jit) for a detailed explanation.

But here's a short description.

> Since v3, JIT has been the default in Tailwind CSS and has brought a lot of
> power to the framework. One of the best additions is arbitrary values, these
> allow you to replace custom CSS with Tailwind CSS-like classes.

Let's use this example.

```html
<ul>
  <li class="p-4 text-sm font-medium whitespace-nowrap">...</li>
  <li class="p-4 text-sm font-medium whitespace-nowrap">...</li>
  <li class="bg-gray-100 p-4 text-sm font-medium whitespace-nowrap">...</li>
</ul>
```

Here we have four repeating classes.

- `whitespace-nowrap`
- `p-4`
- `text-sm`
- `font-medium`

However, only two can be delegated to the parent.

- `text-sm`
- `font-medium`

Here's how it would look without JIT.

```html
<ul class="text-sm font-medium">
  <li class="p-4 whitespace-nowrap">...</li>
  <li class="p-4 whitespace-nowrap">...</li>
  <li class="bg-gray-100 p-4 whitespace-nowrap">...</li>
</ul>
```

We still have `p-4` and `whitespace-nowrap` repeated on all the `<li>` elements.

## Delegating Classes with JIT

Here's how the example looks with JIT.

```html
<ul class="text-sm font-medium *:p-4 *:whitespace-nowrap">
  <li>...</li>
  <li>...</li>
  <li class="bg-gray-100">...</li>
</ul>
```

It's the same as writing this.

```css
& li {
  //
}
```

Which translates to.

> Select all first level children within this element

In our example, the `&` is the `<ul>` and the `*` is the `<li>` elements.

Here's how it would look in CSS.

```css
ul > li {
  //
}
```

And from that, all we're doing is applying CSS but with Tailwind CSS utilities.

```css
ul {
  @apply text-sm font-medium;
}

ul > li {
  @apply p-4 whitespace-nowrap;
}
```

Here's a more
[built-out example using a table component](https://play.tailwindcss.com/pJxSAPRw22)
from HyperUI.

---

I'm unsure about this approach, as arbitrary classes have some downsides.

- Confusing to read
- Confusing to write
- Messy markup
